﻿/* Copyright (c) 2011-2012, Zetatron Consulting
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

* Neither the name of Zetatron Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AionCxxLibrary.Packets;
using AionCxxLibrary.Utilities;
using AionCxxLibrary.Enums;
using WorldServer.Packets.Server;
using AionCxxLibrary.DAO;
using WorldServer.Services;
using WorldServer.DAO;
using WorldServer.Models;

namespace WorldServer.Packets.Client
{
    public class CPkt_ClientVersion : AionClientPacket
    {
        public override void ProcessPacket()
        {
            Connection.SendPacket(new SPkt_ServerVersion());
        }
    }

    public class CPkt_MACAddress : AionClientPacket
    {
        public override void ProcessPacket()
        {
            ReadBytes(22);
            string mac = ReadString();
            Log.Debug(Connection.GetRemoteIP() + " <=> " + mac);
        }
    }

    public class CPkt_MACAddressUpdate : AionClientPacket
    {
        public override void ProcessPacket()
        {
            
        }
    }

    public class CPkt_Login : AionClientPacket
    {
        public override void ProcessPacket()
        {
            int KeyWorld2 = ReadInt();
            int KeyWorld1 = ReadInt();
            int AccountID = ReadInt();
            int KeyLogin = ReadInt();

            bool Authed = false;
            bool CloseAfter = true;

            // account id 8 = xita, for debugging, when I reboot GS (clear reconnecting account table) i stay on LS (realm list) so I don't restart client every time, so PollAccount will fail ;)
            if (KeyWorld1 == 0 && KeyWorld2 == 0 && AccountID > 0 && KeyLogin > 0 && (NetworkService.PollReconnectingAccount(AccountID) || AccountID == 8) && AccountDAO.CheckSession(AccountID, KeyLogin))
                Authed = true;
            else if (AccountDAO.CheckSession(AccountID, KeyLogin, KeyWorld1, KeyWorld2))
                Authed = true;
            else
                Log.Warn(Connection.GetRemoteIP() + " failed to authenticate with " + AccountID + "/" + KeyLogin + "/" + KeyWorld1 + "/" + KeyWorld2);

            if (Authed)
            {
                Connection.account = AccountDAO.LoadAccount(AccountID);
                WorldConnection wc = (WorldConnection)Connection;
                wc.Keys[0] = KeyLogin;
                wc.Keys[1] = KeyWorld1;
                wc.Keys[2] = KeyWorld2;
                CloseAfter = false;
            }

            Connection.SendPacket(new SPkt_Login());

            if (CloseAfter)
            {
                Connection.Close();
            }

        }
    }

    public class CPkt_Time : AionClientPacket
    {
        public override void ProcessPacket()
        {
            Connection.SendPacket(new SPkt_Time(ReadInt()));
        }
    }

    public class CPkt_ChooseServer : AionClientPacket
    {
        static Random rnd = new Random();

        public override void ProcessPacket()
        {
            int key = rnd.Next();
            WorldConnection wc = ((WorldConnection)Connection);
            AccountDAO.UpdateSession(wc.account.ID, wc.Keys[0], wc.Keys[1], wc.Keys[2], key);
            NetworkService.AddReconnectingAccount(wc.account.ID);
            Connection.SendPacket(new SPkt_ChooseServer(key));
        }
    }

    public class CPkt_KeepAlive : AionClientPacket
    {
        public override void ProcessPacket()
        {
            Connection.SendPacket(new SPkt_KeepAlive());
        }
    }

    public class CPkt_EnterWorldCheck : AionClientPacket
    {
        public override void ProcessPacket()
        {
            Connection.SendPacket(new SPkt_EnterWorldCheck());
        }
    }

    public class CPkt_ClientSettings : AionClientPacket
    {
        public override void ProcessPacket()
        {
            byte type = ReadByte(); // 0 = Settings - 1 = Quick Bars
            ReadShort();
            ReadShort();
            byte[] data = ReadBytes((int)(Length - Position));
            CharacterDAO.UpdateSettings(((WorldConnection)Connection).Character.Template.ID, type, data);
        }
    }

    public class CPkt_WorldQuit : AionClientPacket
    {
        public override void ProcessPacket()
        {
            byte action = ReadByte();

            CharacterService.OnDisconnect(((WorldConnection)Connection).Character);
            ((WorldConnection)Connection).Character = null;

            Connection.SendPacket(new SPkt_WorldQuit(false), action == 0);
        }
    }

    public class CPkt_WorldQuitInit : AionClientPacket
    {
        public override void ProcessPacket()
        {
            
        }
    }

    public class CPkt_UIQuestionResponse : AionClientPacket
    {
        public override void ProcessPacket()
        {
            int QuestionID = ReadInt();
            byte Response = ReadByte();
            (Connection as WorldConnection).Character.UI.QuestionResponse(QuestionID, Response == 1);
        }
    }

    public class CPkt_TargetChange : AionClientPacket
    {
        public override void ProcessPacket()
        {
            int TargetGUID = ReadInt();
            byte type = ReadByte();

            AionObject target;
            try
            {
                target = LevelService.Objects[TargetGUID];
            }
            catch (Exception)
            {
                target = null;
            }

            if (target == null)
            {
                (Connection as WorldConnection).Character.Target = null;
            }
            else
            {
                if (type == 1)
                    (Connection as WorldConnection).Character.Target = target.Target;
                else
                    (Connection as WorldConnection).Character.Target = target;
            }
            // Send Player Packet
            // Broadcast NearbyTargetUpdate
        }
    }

}
